<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>FocusManager Node Plugin</title>
    <link rel="stylesheet" href="http://yui.yahooapis.com/3.4.0pr3/build/cssgrids/grids-min.css">
    <link rel="stylesheet" href="../assets/css/main.css">
    <link rel="stylesheet" href="../assets/vendor/prettify/prettify-min.css">
    <script src="../../build/yui/yui-min.js"></script>
</head>
<body>

<div id="doc">
    <h1>FocusManager Node Plugin</h1>

    
        <a href="#toc" class="jump">Jump to Table of Contents</a>
    

    <div class="yui3-g">
        <div id="main" class="yui3-u">
            <div class="content"><div class="intro">
    <p>
        When designing widgets that manage a set of descendant controls (i.e. buttons
        in a toolbar, tabs in a tablist, menuitems in a menu, etc.) it is important to
        limit the number of descendants in the browser's default tab flow.  The fewer
        number of descendants in the default tab flow, the easier it is for keyboard
        users to navigate between widgets by pressing the tab key.  When a widget has
        focus it should provide a set of shortcut keys (typically the arrow keys)
        to move focus among its descendants.
    </p>

    <p>
        To this end, the Focus Manager Node Plugin makes it easy to define a Node's
        focusable descendants, define which descendant should be in the default tab
        flow, and define the keys that move focus among each descendant.
        Additionally, as the CSS
        <a href="http://www.w3.org/TR/CSS21/selector.html#x38"><code>:focus</code></a>
        pseudo class is not supported on all elements in all browsers,
        the Focus Manager Node Plugin provides an easy, cross-browser means of
        styling focus.
    </p>
</div>

<h2 id="getting-started">Getting Started</h2>

<p>
To include the source files for FocusManager Node Plugin and its dependencies, first load
the YUI seed file if you haven't already loaded it.
</p>

<pre class="code prettyprint">&lt;script src=&quot;http:&#x2F;&#x2F;yui.yahooapis.com&#x2F;3.4.0&#x2F;build&#x2F;yui&#x2F;yui-min.js&quot;&gt;&lt;&#x2F;script&gt;</pre>


<p>
Next, create a new YUI instance for your application and populate it with the
modules you need by specifying them as arguments to the <code>YUI().use()</code> method.
YUI will automatically load any dependencies required by the modules you
specify.
</p>

<pre class="code prettyprint">&#x2F;&#x2F; Create a new YUI instance and populate it with the required modules.
YUI().use(&#x27;node-focusmanager&#x27;, function (Y) {
    &#x2F;&#x2F; FocusManager Node Plugin is available and ready for use. Add implementation
    &#x2F;&#x2F; code here.
});</pre>


<p>
For more information on creating YUI instances and on the
<a href="http://yuilibrary.com/yui/docs/api/classes/YUI.html#method_use"><code>use()</code> method</a>, see the
documentation for the <a href="../yui/index.html">YUI Global object</a>.
</p>


<h2 id="using-the-focus-manager-node-plugin">Using the Focus Manager Node Plugin</h2>

<p>
To use the Focus Manager Node Plugin, start by identifying the parent element
of the elements whose focus is to be managed.  For example, consider the
following toolbar HTML:
</p>

<pre class="code prettyprint">&lt;div id=&quot;toolbar-1&quot;&gt;
    &lt;input type=&quot;button&quot; name=&quot;btn-add&quot; value=&quot;Add&quot;&gt;
    &lt;input type=&quot;button&quot; name=&quot;btn-edit&quot; value=&quot;Edit&quot;&gt;
    &lt;input type=&quot;button&quot; name=&quot;btn-print&quot; value=&quot;Print&quot;&gt;
    &lt;input type=&quot;button&quot; name=&quot;btn-delete&quot; value=&quot;Delete&quot;&gt;
    &lt;input type=&quot;button&quot; name=&quot;btn-open&quot; value=&quot;Open&quot;&gt;
    &lt;input type=&quot;button&quot; name=&quot;btn-save&quot; value=&quot;Save&quot;&gt;
&lt;&#x2F;div&gt;</pre>


<p>
To manage the focus of each button in the toolbar, start by retrieving a
<a href="../node">Node</a> instance representing the toolbar's root element
(<code>&#60;div id="toolbar-1"&#62;</code>).
Next, call the Node's
<a href="http://yuilibrary.com/yui/docs/api/classes/Node.html#method_plug"><code>plug</code></a>
method, passing in a reference to the Focus Manager Node Plugin
(<code>Y.Plugin.NodeFocusManager</code>) as the first argument, followed by an
object literal of configuration attributes as the second.
</p>
<p>Use the
<a href="http://yuilibrary.com/yui/docs/api/classes/plugin.NodeFocusManager.html#config_descendants"><code>descendants</code></a>
configuration attribute to specify the child nodes of the root node whose
focus is to be managed.  The
<a href="http://yuilibrary.com/yui/docs/api/classes/plugin.NodeFocusManager.html#config_descendants"><code>descendants</code></a>
configuration attribute accepts a string representing a CSS selector, making it
very easy to identify the elements whose focus should be managed.  For the
toolbar, a value of "input" will be passed as the value of the
<a href="http://yuilibrary.com/yui/docs/api/classes/plugin.NodeFocusManager.html#config_descendants"><code>descendants</code></a>
configuration attribute.
</p>
<p>
Use the
<a href="http://yuilibrary.com/yui/docs/api/classes/plugin.NodeFocusManager.html#config_keys"><code>keys</code></a>
configuration attribute to identify which keys move focus between each of the
specified descendant Nodes.  The
<a href="http://yuilibrary.com/yui/docs/api/classes/plugin.NodeFocusManager.html#config_keys"><code>keys</code></a>
configuration attribute accepts an object literal, the format of which is
<code>{ next: "down:40", previous: "down:38" }</code>.  The value for the
<code>next</code> and <code>previous</code> sub attributes are used to attach
<a href="../event/index.html#keylistener"><code>key</code></a> event listeners.  Each
value represents the type of event
("down" for <code>mousedown</code>, "up" for <code>mouseup</code>, and
"press" for <code>keypress</code>) and key codes ("40" for the down arrow key)
to use to navigate to the next/previous descendant.  For the
toolbar the
<a href="http://yuilibrary.com/yui/docs/api/classes/plugin.NodeFocusManager.html#config_keys"><code>keys</code></a>
configuration attribute will be set to a value of
<code>{ next: "down:39", previous: "down:37" }</code>, enabling the user to
move focus among each button using the left and right arrows keys.
(See
the <a href="../event/index.html#keylistener">Using the key Event</a> section of
the Event documentation for more information on "key" event listeners.)
</p>

<pre class="code prettyprint">YUI().use(&quot;node-focusmanager&quot;, function(Y) {

&#x2F;&#x2F;  Retrieve the Node instance representing the toolbar
&#x2F;&#x2F;  (&lt;div id=&quot;toolbar&quot;&gt;) and call the &quot;plug&quot; method
&#x2F;&#x2F;  passing in a reference to the Focus Manager Node Plugin.

var toolbar = Y.one(&quot;#toolbar-1&quot;);

toolbar.plug(Y.Plugin.NodeFocusManager, {

    &#x2F;&#x2F; CSS Selector indicating the descendant Nodes whose focus to manage

    descendants: &quot;input&quot;,

    &#x2F;&#x2F;  Move focus the buttons in the toolbar by pressing the left and
    &#x2F;&#x2F;  right arrow keys

    keys: { next: &quot;down:39&quot;, previous: &quot;down:37&quot; }

});

});</pre>


<p>
Use the
<a href="http://yuilibrary.com/yui/docs/api/classes/plugin.NodeFocusManager.html#config_circular"><code>circular</code></a>
configuration attribute to indicate that focus should be directed to the first
or last descendant when the user has navigated to the first or last descendant.
</p>

<pre class="code prettyprint">YUI().use(&quot;node-focusmanager&quot;, function(Y) {

&#x2F;&#x2F;  Retrieve the Node instance representing the toolbar
&#x2F;&#x2F;  (&lt;div id=&quot;toolbar&quot;&gt;) and call the &quot;plug&quot; method
&#x2F;&#x2F;  passing in a reference to the Focus Manager Node Plugin.

var toolbar = Y.one(&quot;#toolbar-1&quot;);

toolbar.plug(Y.Plugin.NodeFocusManager, {

    &#x2F;&#x2F; CSS Selector indicating the descendant Nodes whose focus to manage

    descendants: &quot;input&quot;,

    &#x2F;&#x2F;  Move focus the buttons in the toolbar by pressing the left and
    &#x2F;&#x2F;  right arrow keys

    keys: { next: &quot;down:39&quot;, previous: &quot;down:37&quot; },

    circular: true

});

});</pre>


<h3 id="activedescendant-attribute">The <code>activeDescendant</code> Attribute</h3>

<p>
The <a href="http://yuilibrary.com/yui/docs/api/classes/plugin.NodeFocusManager.html#config_activeDescendant"><code>activeDescendant</code></a>
attribute represents which of the Focus Manager's
<a href="http://yuilibrary.com/yui/docs/api/classes/plugin.NodeFocusManager.html#config_descendants"><code>descendants</code></a> is either
currently focused or is focusable (<code>tabIndex</code> attribute is set to 0).
As the user moves focus among the Focus Manager's defined descendants, the <a href="../api/plugin.NodeFocusManager.html#config_activeDescendant"><code>activeDescendant</code></a>
configuration attribute is updated to remain in sync with the currently
focused descendant.
</p>
<p>
The
<a href="http://yuilibrary.com/yui/docs/api/classes/plugin.NodeFocusManager.html#config_activeDescendant"><code>activeDescendant</code></a>
configuration attribute can be set two different ways: via markup or via
script.  To set the
<a href="http://yuilibrary.com/yui/docs/api/classes/plugin.NodeFocusManager.html#config_activeDescendant"><code>activeDescendant</code></a>
configuration attribute via markup, simply set the <code>tabIndex</code>
attribute to 0 for the element that should be considered the active descendant.
If the <code>tabIndex</code> attribute isn't set on any of the descendants
the active descendant will be set to 0, or the index of the first
enabled descendant. The following example shows how to make the second button
in the toolbar the active descendant.
</p>

<pre class="code prettyprint">&lt;div id=&quot;toolbar-1&quot;&gt;
    &lt;input type=&quot;button&quot; name=&quot;btn-add&quot; value=&quot;Add&quot;&gt;
    &lt;input type=&quot;button&quot; tabindex=&quot;0&quot; name=&quot;btn-edit&quot; value=&quot;Edit&quot;&gt;
    &lt;input type=&quot;button&quot; name=&quot;btn-print&quot; value=&quot;Print&quot;&gt;
    &lt;input type=&quot;button&quot; name=&quot;btn-delete&quot; value=&quot;Delete&quot;&gt;
    &lt;input type=&quot;button&quot; name=&quot;btn-open&quot; value=&quot;Open&quot;&gt;
    &lt;input type=&quot;button&quot; name=&quot;btn-save&quot; value=&quot;Save&quot;&gt;
&lt;&#x2F;div&gt;</pre>


<p>
The
<a href="http://yuilibrary.com/yui/docs/api/classes/plugin.NodeFocusManager.html#config_activeDescendant"><code>activeDescendant</code></a>
configuration attribute can also be set via the object literal of configuration
attributes passed to the
<a href="http://yuilibrary.com/yui/docs/api/classes/Node.html#method_plug"><code>plug</code></a>
method.
</p>

<pre class="code prettyprint">YUI().use(&quot;node-focusmanager&quot;, function(Y) {

&#x2F;&#x2F;  Retrieve the Node instance representing the toolbar
&#x2F;&#x2F;  (&lt;div id=&quot;toolbar&quot;&gt;) and call the &quot;plug&quot; method
&#x2F;&#x2F;  passing in a reference to the Focus Manager Node Plugin.

var toolbar = Y.one(&quot;#toolbar-1&quot;);

toolbar.plug(Y.Plugin.NodeFocusManager, {

    &#x2F;&#x2F; CSS Selector indicating the descendant Nodes whose focus to manage

    descendants: &quot;input&quot;,

    &#x2F;&#x2F;  Move focus the buttons in the toolbar by pressing the left and
    &#x2F;&#x2F;  right arrow keys

    keys: { next: &quot;down:39&quot;, previous: &quot;down:37&quot; },

    &#x2F;&#x2F;  Make the second button in the toolbar the active descendant
    activeDescendant: 1

});

});</pre>


<p>The
<a href="http://yuilibrary.com/yui/docs/api/classes/plugin.NodeFocusManager.html#config_activeDescendant"><code>activeDescendant</code></a>
configuration attribute can also be set at runtime via the
<a href="http://yuilibrary.com/yui/docs/api/classes/Attribute.html#method_set"><code>set</code></a>
method.
</p>

<pre class="code prettyprint">YUI().use(&quot;node-focusmanager&quot;, function(Y) {

&#x2F;&#x2F;  Retrieve the Node instance representing the toolbar
&#x2F;&#x2F;  (&lt;div id=&quot;toolbar&quot;&gt;) and call the &quot;plug&quot; method
&#x2F;&#x2F;  passing in a reference to the Focus Manager Node Plugin.

var toolbar = Y.one(&quot;#toolbar-1&quot;);

toolbar.plug(Y.Plugin.NodeFocusManager, {

    &#x2F;&#x2F; CSS Selector indicating the descendant Nodes whose focus to manage

    descendants: &quot;input&quot;,

    &#x2F;&#x2F;  Move focus the buttons in the toolbar by pressing the left and
    &#x2F;&#x2F;  right arrow keys

    keys: { next: &quot;down:39&quot;, previous: &quot;down:37&quot; }

});

&#x2F;&#x2F;  Make the second button in the toolbar the active descendant
toolbar.focusManager.set(&quot;activeDescendant&quot;, 1);

});</pre>


<h3 id="styling-focus">Styling Focus</h3>

<p>
One of the challenges to styling the focus state of HTML elements is that
support for the CSS
<a href="http://www.w3.org/TR/CSS21/selector.html#x38"><code>:focus</code></a>
pseudo class is limited to the <code>a</code> element in Internet Explorer.
To fix this problem, the Focus Manager Node Plugin provides a
<a href="http://yuilibrary.com/yui/docs/api/classes/plugin.NodeFocusManager.html#config_focusClass"><code>focusClass</code></a>
configuration attribute that makes it easy to style focus across <em>all</em>
elements in <em>all</em> browsers</a>.
</p>
<p>
The
<a href="http://yuilibrary.com/yui/docs/api/classes/plugin.NodeFocusManager.html#config_focusClass"><code>focusClass</code></a>
configuration attribute can be used one of two ways.  The first way is to
simply pass a string representing the class name to be applied to the currently
focused descendant Node instance.  For example, to apply a class of "focus" to
each button in the toolbar, set the the
<a href="http://yuilibrary.com/yui/docs/api/classes/plugin.NodeFocusManager.html#config_focusClass"><code>focusClass</code></a>
configuration attribute to a value of "focus":
</p>

<pre class="code prettyprint">YUI().use(&quot;node-focusmanager&quot;, function(Y) {

&#x2F;&#x2F;  Retrieve the Node instance representing the toolbar
&#x2F;&#x2F;  (&lt;div id=&quot;toolbar&quot;&gt;) and call the &quot;plug&quot; method
&#x2F;&#x2F;  passing in a reference to the Focus Manager Node Plugin.

var toolbar = Y.one(&quot;#toolbar-1&quot;);

toolbar.plug(Y.Plugin.NodeFocusManager, {

    &#x2F;&#x2F; CSS Selector indicating the descendant Nodes whose focus to manage

    descendants: &quot;input&quot;,

    &#x2F;&#x2F;  Move focus the buttons in the toolbar by pressing the left and
    &#x2F;&#x2F;  right arrow keys

    keys: { next: &quot;down:39&quot;, previous: &quot;down:37&quot; },

    focusClass: &quot;focus&quot;

});

});</pre>


<p>
Often styling focusable elements such as <code>&#60;input&#62;</code>s
requires wrapping them in decorator elements, since <code>&#60;input&#62;</code>
elements cannot have children.  In such cases, it is likely the class name used
to style focus would be applied to the element decorating the focused
descendant, rather than the descendant itself.  For this reason, it is also
possible to pass an object literal as the value of the
<a href="http://yuilibrary.com/yui/docs/api/classes/plugin.NodeFocusManager.html#config_focusClass"><code>focusClass</code></a>
configuration attribute that defines not only the class name to be used to
indicate focus, but a function used to retrieve the Node instance to which
the class name should be applied.  For example, if each button in the toolbar
where decorated by a <code>&#60;span&#62;</code>, the "focus" class could be
applied to the parent <code>&#60;span&#62;</code> of the focused
<code>&#60;input&#62;</code> using the following code:
</p>

<pre class="code prettyprint">YUI().use(&quot;node-focusmanager&quot;, function(Y) {

&#x2F;&#x2F;  Retrieve the Node instance representing the toolbar
&#x2F;&#x2F;  (&lt;div id=&quot;toolbar&quot;&gt;) and call the &quot;plug&quot; method
&#x2F;&#x2F;  passing in a reference to the Focus Manager Node Plugin.

var toolbar = Y.one(&quot;#toolbar-1&quot;);

toolbar.plug(Y.Plugin.NodeFocusManager, {

    &#x2F;&#x2F; CSS Selector indicating the descendant Nodes whose focus to manage

    descendants: &quot;input&quot;,

    &#x2F;&#x2F;  Move focus the buttons in the toolbar by pressing the left and
    &#x2F;&#x2F;  right arrow keys

    keys: { next: &quot;down:39&quot;, previous: &quot;down:37&quot; },

    focusClass: {
        className: &quot;focus&quot;, &#x2F;&#x2F;  The class name to use
        fn: function (node) {
            &#x2F;&#x2F;  The Node instance to which the class should be applied
            return node.get(&quot;parentNode&quot;);
        }
    }

});

});</pre>


<p>
As demonstrated in the example, the function passed as the value of the
<code>fn</code> property is passed a reference to the currently focused
descendant.  That Node reference is then used to return the Node to which the
class name is to be applied.
</p>

<h3 id="managing-focus">Managing Focus</h3>

<p>
The Focus Manager Node Plugin manages focus among its defined descendants as an
atomic operation: the Focus Manager's
<a href="http://yuilibrary.com/yui/docs/api/classes/plugin.NodeFocusManager.html#config_focused"><code>focused</code></a>
configuration attribute is set to
<code>true</code> the first time any descendant is focused, and is set to
<code>false</code> the first time no descendant is focused.  The
<a href="http://yuilibrary.com/yui/docs/api/classes/plugin.NodeFocusManager.html#config_focused"><code>focused</code></a>
configuration attribute is read only, and is set either via user interaction
(the user focuses one of the defined descendant elements using either the
keyboard or the mouse), or programmatically via the
<a href="http://yuilibrary.com/yui/docs/api/classes/plugin.NodeFocusManager.html#method_focus"><code>focus</code></a>
and
<a href="http://yuilibrary.com/yui/docs/api/classes/plugin.NodeFocusManager.html#method_blur"><code>blur</code></a>
methods, as illustrated in the following example:
</p>

<pre class="code prettyprint">YUI().use(&quot;node-focusmanager&quot;, function(Y) {

&#x2F;&#x2F;  Retrieve the Node instance representing the toolbar
&#x2F;&#x2F;  (&lt;div id=&quot;toolbar&quot;&gt;) and call the &quot;plug&quot; method
&#x2F;&#x2F;  passing in a reference to the Focus Manager Node Plugin.

var toolbar = Y.one(&quot;#toolbar-1&quot;);

toolbar.plug(Y.Plugin.NodeFocusManager, {

    &#x2F;&#x2F; CSS Selector indicating the descendant Nodes whose focus to manage

    descendants: &quot;input&quot;,

    &#x2F;&#x2F;  Move focus the buttons in the toolbar by pressing the left and
    &#x2F;&#x2F;  right arrow keys

    keys: { next: &quot;down:39&quot;, previous: &quot;down:37&quot; }

});


&#x2F;&#x2F;  Listen for when the &quot;focused&quot; attribute changes

toolbar.focusManager.after(&quot;focusedChange&quot;, function (event) {

    if (event.newVal) {
        Y.log(&quot;The toolbar has focus&quot;);
    }
    else {
        Y.log(&quot;The toolbar has lost focus&quot;);
    }

});

&#x2F;&#x2F;  Focus the current active descendant, setting the &quot;focused&quot; attribute to true

toolbar.focusManager.focus();

&#x2F;&#x2F;  Focus the second descendant in the toolbar, making it the active descendant
&#x2F;&#x2F;  (this won&#x27;t change the &quot;focused&quot; attribute, meaning the &quot;focusedChange&quot;
&#x2F;&#x2F;  event handler won&#x27;t be called.)

toolbar.focusManager.focus(1);


&#x2F;&#x2F;  Blur the current active descendant, setting the &quot;focused&quot; attribute to false
&#x2F;&#x2F;  and causing the &quot;focusedChange&quot; event handler to be called.

toolbar.focusManager.blur();

});</pre>


<h3 id="best-practices">Best Practices</h3>

<p>
While it is possible to use the Focus Manager Node Plugin to manage focus
among descendants of any type, it is recommended to use it with elements that
are natively in the the browser's default tab flow. Doing so provides two primary
benefits:  The first is that your code will work in all popular browsers, since some browsers don't support
the
<a href="http://www.w3.org/TR/html401/interact/forms.html#adef-tabindex" title="Forms in HTML documents"><code>tabIndex</code></a>
attribute on all elements.  Sticking with the elements that natively support <a href="http://www.w3.org/TR/html401/interact/forms.html#adef-tabindex" title="Forms in HTML documents"><code>tabIndex</code></a>
as defined in the HTML 4.01 specification will ensure better cross-browser
keyboard support.
</p>

<p>The second benefit is that by using the set of natively
focusable HTML elements, users of screen readers will still perceive the
Focus Manager's defined descendants as actionable/clickable elements.</p>
</div>
        </div>

        <div id="sidebar" class="yui3-u">
            
                <div id="toc" class="sidebox">
                    <div class="hd">
                        <h2 class="no-toc">Table of Contents</h2>
                    </div>

                    <div class="bd">
                        <ul class="toc">
<li>
<a href="#getting-started">Getting Started</a>
</li>
<li>
<a href="#using-the-focus-manager-node-plugin">Using the Focus Manager Node Plugin</a>
<ul class="toc">
<li>
<a href="#activedescendant-attribute">The <code>activeDescendant</code> Attribute</a>
</li>
<li>
<a href="#styling-focus">Styling Focus</a>
</li>
<li>
<a href="#managing-focus">Managing Focus</a>
</li>
<li>
<a href="#best-practices">Best Practices</a>
</li>
</ul>
</li>
</ul>
                    </div>
                </div>
            

            
                <div class="sidebox">
                    <div class="hd">
                        <h2 class="no-toc">Examples</h2>
                    </div>

                    <div class="bd">
                        <ul class="examples">
                            
                                
                                    <li data-description="Creating an accessible toolbar using the Focus Manager Node Plugin and Node&#x27;s support for the WAI-ARIA Roles and States.">
                                        <a href="node-focusmanager-1.html">Accessible Toolbar</a>
                                    </li>
                                
                            
                                
                                    <li data-description="Creating an accessible menu button using the Focus Manager Node Plugin, Event&#x27;s delegation support and mouseenter event, along with the Overlay widget and Node&#x27;s support for the WAI-ARIA Roles and States.">
                                        <a href="node-focusmanager-3.html">Accessible Menu Button</a>
                                    </li>
                                
                            
                        </ul>
                    </div>
                </div>
            

            
        </div>
    </div>
</div>

<script src="../assets/vendor/prettify/prettify-min.js"></script>
<script>prettyPrint();</script>

</body>
</html>
